package org.crsystems.crbooks.models;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.crsystems.crbooks.application.CRBooks;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;

import com.vaadin.annotations.AutoGenerated;
import com.vaadin.terminal.FileResource;

@Entity
@Table(name="Books")
public class Book extends ModelBase<Book, Integer> {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column(updatable = false, nullable = false)
	private Integer bookID;

	@Basic
	private String title;
	
	@ManyToOne(fetch=FetchType.EAGER)
	private Author author;
	
	@ManyToOne(fetch=FetchType.EAGER)
	private Publisher publisher;	
	
	@Basic
	private Integer stock;
	
	@Lob
	private String description;
	
	@Basic
	private Integer edition;
	
	@Basic
	private Double price;
	
	@ManyToMany(fetch=FetchType.EAGER)
	private List<BookCategory> categories;
	
	@Override
	public String getTableName() {
		// TODO Auto-generated method stub
		return "Books";
	}

	public Integer getBookID() {
		return bookID;
	}

	public void setBookID(Integer bookID) {
		this.bookID = bookID;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public Author getAuthor() {
		return author;
	}

	public void setAuthor(Author author) {
		this.author = author;
	}

	@Override
	public boolean isValid() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Map<String, String> getErrorFields() {
		// TODO Auto-generated method stub
		return null;
	}

	public static Book getByID(Integer key) {
		return ModelBase.getByID(Book.class, Integer.class, key);
	}

	public Integer getStock() {
		return stock;
	}

	public void setStock(Integer stock) {
		this.stock = stock;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public Integer getEdition() {
		return edition;
	}

	public void setEdition(Integer edition) {
		this.edition = edition;
	}

	public Double getPrice() {
		return price;
	}

	public void setPrice(Double price) {
		this.price = price;
	}

	public List<BookCategory> getCategories() {
		return categories;
	}

	public void setCategories(List<BookCategory> categories) {
		this.categories = categories;
	}

	public Publisher getPublisher() {
		return publisher;
	}

	public void setPublisher(Publisher publisher) {
		this.publisher = publisher;
	}

	public static List<Book> getAll() {
		return ModelBase.getAll(Book.class, Integer.class, "Book");
	}
	

	public void addCategory(BookCategory c) {
		if (this.categories == null) {
			this.categories = new ArrayList<BookCategory>();
		}
		for (BookCategory category : this.categories) {
			if (category.getBookCategoryID() == c.getBookCategoryID()) return;
		}
		categories.add(c);
	}	
	
	public boolean equals(Object other) {
		if (other != null && other instanceof Book) {
			return this.bookID == ((Book)other).getBookID();
		}
		return super.equals(other);
	}

	public static List<Book> getMostSoldBooks(int limit) {
		List<Book> list = Book.getAll();
		List<Book> result = new ArrayList<Book>();
		if (list == null) list = new ArrayList<Book>();
		for (int i = 0; i < limit; i++) {
			if (i < list.size()){
				result.add(list.get(i));
			}
		}
		return result;
	}

	public static List<Book> getByTitle(String title) {
		Criterion c = Restrictions.like("title", "%" + title + "%"); 
		List<Book> list =  ModelBase.getByCriterion(Book.class, c);
		if (list == null) list = new ArrayList<Book>();
		return list;
	}
	
	public static List<Book> getByAuthor(Author author) {
		Criterion c = Restrictions.sqlRestriction(String.format("author_authorID = %d", author.getAuthorID()));
		List<Book> list =  ModelBase.getByCriterion(Book.class, c);
		if (list == null) list = new ArrayList<Book>();
		return list;
	}
	
	public static List<Book> getByAuthorName(String authorName) {
		List<Author> authors = Author.getByName(authorName);
		List<Book> list = new ArrayList<Book>();
		for (Author author : authors) {
			list.addAll(Book.getByAuthor(author));
		}
		return list;
	}
	
	public static List<Book> getByTitleAndAuthor(String title, Author author) {
		Criterion c = Restrictions.and(Restrictions.eq("authorID", author.getAuthorID()),
				                       Restrictions.like("title", "%" + title + "%"));
		List<Book> list =  ModelBase.getByCriterion(Book.class, c);
		if (list == null) list = new ArrayList<Book>();
		return list;
	}
	
	public static List<Book> getByTitleAndAuthorName(String title, String name) {
		List<Author> authors = Author.getByName(name);
		List<Book> result = new ArrayList<Book>();
		for (Author author : authors) {
			List<Book> list =  Book.getByTitleAndAuthor(title, author);
			result.addAll(list);
		}
		return result;
	}

	public List<BookComment> getComments() {
		return BookComment.getByBook(this);
	}

	public void setComments(List<BookComment> comments) {
		for (BookComment comment : comments) {
			comment.setBook(this);
		}
	}

	public static List<Book> getByPublisher(Publisher publisher) {
		Criterion c = Restrictions.eq("publisherID", publisher.getPublisherID());
		return ModelBase.getByCriterion(Book.class, c);
	}

	public String thumbName() {
		System.out.println(String.format("books/book-tumb%03d.png", this.bookID));
		return String.format("img/books/book-tumb%03d.png", this.bookID);
	}
}
